package org.example.infrastructure.common.base;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.example.common.util.GenericsUtil;
import org.example.common.util.SpringUtil;
import org.example.domain.common.base.BaseEntity;
import org.example.domain.common.base.BaseGateway;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public class BaseGatewayImpl<I extends Serializable, Entity extends BaseEntity<I>, DataObject extends BaseDO<I>, Mapper extends BaseMapper<DataObject>, Convertor extends BaseConvertor<DataObject, Entity>>
        extends ServiceImpl<Mapper, DataObject> implements BaseGateway<I, Entity> {

    protected final String LIMIT_ONE = "limit 1";

    protected final Class<Convertor> convertorClass = GenericsUtil.getTypeArgument(getClass(), 4);

    protected final Convertor convertor = SpringUtil.getBean(convertorClass);

    @Override
    public Entity loadById(I id) {
        DataObject dataObject = getById(id);
        return convertor.toEntity(dataObject);
    }

    @Override
    public List<Entity> loadByIds(Collection<I> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Lists.newArrayList();
        }
        List<DataObject> dataObjectList = listByIds(ids);
        return convertor.toEntityList(dataObjectList);
    }

    @Override
    public I insert(Entity entity) {
        entity.setPrimaryId(null);
        DataObject dataObject = convertor.toDO(entity);
        save(dataObject);
        return dataObject.getPrimaryId();
    }

    @Override
    public boolean insertBatch(Collection<Entity> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return false;
        }
        entities.forEach(entity -> entity.setPrimaryId(null));
        return saveBatch(convertor.toDOList(entities));
    }

    @Override
    public boolean update(Entity entity) {
        return updateById(convertor.toDO(entity));
    }

    @Override
    public boolean updateBatch(Collection<Entity> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return false;
        }
        return updateBatchById(convertor.toDOList(entities));
    }

    @Override
    public I insertOrUpdate(Entity entity) {
        if (Objects.isNull(entity.getPrimaryId())) {
            return insert(entity);
        } else {
            update(entity);
            return entity.getPrimaryId();
        }
    }

    @Override
    public boolean insertOrUpdateBatch(Collection<Entity> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return false;
        }
        return saveOrUpdateBatch(convertor.toDOList(entities));
    }

    @Override
    public boolean deleteById(I id) {
        return removeById(id);
    }

    @Override
    public boolean deleteBatchByIds(Collection<I> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        return removeByIds(ids);
    }
}
